#include <iostream>
using std::cout;
using std::endl;
#include <stdio.h>

#include "info.h"
#include "disk.h"
#include "ioctl.h"

void cpu_info() {
  cout << "------------ cpu info ------------" << endl;

  std::string data;
  cpuinfo::get_company(data);
  cout << "CPU Manufacturer: " << data << endl;

  int family, model, stepping;
  cpuinfo::get_base_param(family, model, stepping);
  cout << "CPU Base Parameters: " 
  << "Family: " << family << " "
  << "Model: " << model << " "
  << "Stepping ID: " << stepping
  << endl;

  int a, b, c, d;
  cpuinfo::get_id(a, b, c, d);
  char cpuid_buf[128] = { 0 };
  sprintf(cpuid_buf, "%#010x %#010x %#010x %#010x", a, b, c, d);
  cout << "CPU Serial Number: " << cpuid_buf << endl;

  cpuinfo::get_brand(data);
  cout << "CPU Brand Name: " << data << endl;

  cout << "CPU Count: " << cpuinfo::get_count() << endl;
  cout << "CPU Count Enabled: " << cpuinfo::get_count_enabled() << endl;
}

void sys_info() {
  cout << "------------ system info ------------" << endl;
  cout << "Memory Physics Pages: " << sysinfo::pages() << endl;
  cout << "Memory Free Pages: " << sysinfo::pages_enabled() << endl;
  cout << "Memory Page Size: " << sysinfo::page_size() << endl;
  cout << "Memory Size: " << sysinfo::size()
       << " (" << (double)sysinfo::size() / (double)(1024 * 1024 * 1024) << "GB)" << endl;
  cout << "Memory Free Size: " << sysinfo::size_free()
       << " (" << (double)sysinfo::size_free() / (double)(1024 * 1024 * 1024) << "GB)" << endl;

  struct utsname os;
  sysinfo::uname(&os);
  cout << "OS System Name: " << os.sysname << endl;
  cout << "OS Node Name: " << os.nodename << endl;
  cout << "OS Release: " << os.release << endl;
  cout << "OS Version: " << os.version << endl;
  cout << "OS Machine: " << os.machine << endl;

  cout << "Install Time: " << sysinfo::format_date(sysinfo::install_time()) << endl;
}

void print_info() {
  cout << "------------ print info ------------" << endl;
  cout << "----- OS Info -----" << endl;
  printinfo::os_info();
  cout << "----- CPU Info -----" << endl;
  printinfo::cpu_info();
  cout << "----- Memory Info -----" << endl;
  printinfo::memory_info();
  cout << "----- Disk Info -----" << endl;
  printinfo::disk_info();
  cout << "----- Network Info -----" << endl;
  printinfo::network_info();
}

void groupuser_info() {
  cout << "------------ groupuser info ------------" << endl;
  struct passwd user;
  sysinfo::user(sysinfo::cur_user(), user);
  cout << "User Name: " << user.pw_name << endl;
  cout << "User Password: " << user.pw_passwd << endl;
  cout << "User ID: " << user.pw_uid << endl;
  cout << "Group ID: " << user.pw_gid << endl;
  cout << "Real Name: " << user.pw_gecos << endl;
  cout << "Home Directory: " << user.pw_dir << endl;
  cout << "Shell Program: " << user.pw_shell << endl;
  cout << "--- gup ----" << endl;
  sysinfo::sgup_info gup;
  sysinfo::group(user.pw_gid, gup);
  cout << "Group ID: " << gup.gid << endl;
  cout << "Group Name: " << gup.name << endl;
  cout << "Group Users: " << endl;
  for (std::set<std::string>::iterator it = gup.users.begin(); it != gup.users.end(); ++it) {
    cout << (*it) << " ";
  }
  cout << endl;

  cout << "---- groups ---" << endl;

  sysinfo::sgu_info groups;
  sysinfo::groupusers(groups);
  cout << "Users: " << endl;
  for (std::set<std::string>::iterator it = groups.users.begin(); it != groups.users.end(); ++it) {
    cout << (*it) << " ";
  }
  cout << endl;

  cout << "ID\tName\tUsers" << endl;
  for (std::vector<sysinfo::sgup_info>::iterator it = groups.groups.begin(); it != groups.groups.end(); ++it) {
    gup = *it;
    cout << gup.gid << "\t";
    cout << gup.name << "\t(";
    for (std::set<std::string>::iterator it = gup.users.begin(); it != gup.users.end(); ++it) {
      cout << (*it) << " ";
    }
    cout << ")" << endl;
  }
}

void loginout_info() {
  cout << "---- login out ---" << endl;
  std::vector<sysinfo::sloginout_info> info;
  sysinfo::loginout_info(info);
  for (std::vector<sysinfo::sloginout_info>::iterator it = info.begin(); it != info.end(); ++it) {
    sysinfo::sloginout_info si = (*it);
    cout << si.user << "\t";
    cout << si.line << "\t";

    if (si.host.empty()) {
      cout << "               " << "\t";
    } else {
      cout << si.host << "\t";
    }

    cout << sysinfo::format_date(si.login.sec) << " - ";

    if (si.still) {
      cout << "still              " << "\t";
      cout << "logged in";
    } else {
      cout << sysinfo::format_date(si.logout.sec) << "\t";
      cout << sysinfo::format_time(si.logout.sec - si.login.sec);
    }

    cout << endl;;
  }
}

void poweronoff_info() {
  cout << "---- power on off ---" << endl;
  std::vector<sysinfo::spoweronoff_info> info;
  sysinfo::poweronoff_info(info);
  for (std::vector<sysinfo::spoweronoff_info>::iterator it = info.begin(); it != info.end(); ++it) {
    sysinfo::spoweronoff_info si = (*it);

    cout << sysinfo::format_date(si.on.sec) << " - ";

    if (si.still) {
      cout << "still              " << "\t";
      cout << "on line";
    } else {
      cout << sysinfo::format_date(si.off.sec) << "\t";
      cout << sysinfo::format_time(si.off.sec - si.on.sec);
    }

    cout << endl;;
  }
}

void disk_info(const char *dev) {
  cout << "---- disk info ---" << endl;
    

  std::set<std::string> info;
  device::scan_disk(info);

  cout << "Type\tdev\tvendor\tproduct\tserial\tversion\t" << endl;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it) {
    cout << (*it) << endl;
    device::sdisk_info si;
    device::disk_info(*it, &si);
  }
  cout << "count: " << info.size() << endl;
}

//-------------------------------//
void scan_memory() {
  cout << "---- scan_memory ---" << endl;
  std::set<std::string> info;
  device::scan_memory(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_bios() {
  cout << "---- scan_bios ---" << endl;
  std::set<std::string> info;
  device::scan_bios(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_board() {
  cout << "---- scan_board ---" << endl;
  std::set<std::string> info;
  device::scan_board(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_system() {
  cout << "---- scan_system ---" << endl;
  std::set<std::string> info;
  device::scan_system(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_chassis() {
  cout << "---- scan_chassis ---" << endl;
  std::set<std::string> info;
  device::scan_chassis(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_connector() {
  cout << "---- scan_connector ---" << endl;
  std::set<std::string> info;
  device::scan_connector(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_diaplay() {
  cout << "---- scan_diaplay ---" << endl;
  std::set<std::string> info;
  device::scan_diaplay(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

void scan_network() {
  cout << "---- scan_network ---" << endl;
  std::set<std::string> info;
  device::scan_network(info);

  int i = 0;
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it, ++i) {
    cout << "num " << i << ":" << endl;
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

//--------------------------------------//
void ioctl_scan_disk() {
  cout << "---- ioctl_scan_disk ---" << endl;
  std::set<std::string> info;
  ioctrl::scan_disk(info);
  for (std::set<std::string>::iterator it = info.begin(); it != info.end(); ++it) {
    cout << (*it) << endl;
  }
  cout << "count: " << info.size() << endl;
}

int main(int argc, char **argv) {
  cpu_info();
  sys_info();
  //print_info();
  groupuser_info();
  loginout_info();
  poweronoff_info();
  disk_info(argv[1]);

  //
  scan_memory();
  scan_bios();
  scan_board();
  scan_system();
  scan_chassis();
  scan_connector();
  scan_diaplay();
  scan_network();

  cout << endl << "---- ioctl ---" << endl;

  ioctl_scan_disk();

  cout << "--------------------" << endl;
  ioctrl::disk_info(argc > 1 ? argv[1] : "/dev/sda");

  return 0;
}